package com.g3d.core;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.g3d.interfaces.IG3DEngineConstants;
import com.g3d.interfaces.IG3DEngineListener;
import com.g3d.interfaces.IG3DTouchScreen;
import com.g3d.objects.G3DMusic;
import com.g3d.objects.G3DSound;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class G3DEngine extends Activity implements IG3DEngineConstants, Renderer, OnTouchListener
{
	//====================================
	// TODO: engine parameters
	//====================================
	private int _displayWidth = 1;
	private int _displayHeight = 1;
	
	private GLSurfaceView _glView;
	//====================================
	// TODO: game engine managers
	//====================================
	private final G3DMusicManager _musicManager = new G3DMusicManager();
	private final G3DSoundManager _soundManager = new G3DSoundManager();

	//====================================
	// TODO: game engine managers
	//====================================
	private IG3DTouchScreen _touchScreenListener;
	private IG3DEngineListener _engineListener;
	
	//====================================
	// TODO: Activity calls
	//====================================
	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		this._glView = new GLSurfaceView(this);
		this._glView.setRenderer(this);
		this._glView.setOnTouchListener(this);
	
		this.setContentView(this._glView);
	}
	//====================================
	// TODO: engine getters
	//====================================
	public int displayWidth()
	{
		return this._displayWidth;
	}
	public int displayHeight()
	{
		return this._displayHeight;
	}
	
	//====================================
	//TODO:OpenGL calls
	//====================================	
	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) 
	{
		// TODO on create surface view
		G3DState.g3dReset(gl);	// reset OpenGL settings and setup instance
		
		G3DState.g3dInitialize();
		
		G3DState.g3dSetViewWidth(this._glView.getWidth());
		G3DState.g3dSetViewHeight(this._glView.getHeight());
		
		if(this._engineListener != null)
			this._engineListener.onInitialize();
	}
	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) 
	{
		G3DState.g3dSetViewWidth(this._glView.getWidth());
		G3DState.g3dSetViewHeight(this._glView.getHeight());

		if(this._engineListener != null)
			this._engineListener.onScreenResize(width, height);
	}
	@Override
	public void onDrawFrame(GL10 gl) 
	{
		G3DState.g3dClearColor();
		G3DState.g3dClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		
		if(this._engineListener != null)
			this._engineListener.onDraw();
	}

	//====================================
	// TODO: Input and sensor calls 
	//====================================	
	@Override
	public boolean onTouch(View v, MotionEvent event) 
	{
		if(this._touchScreenListener != null)
		{
			if(event.getAction() == MotionEvent.ACTION_DOWN)
				this._touchScreenListener.onPress(event.getX(), event.getY());
			else if(event.getAction() == MotionEvent.ACTION_MOVE)
				this._touchScreenListener.onMove(event.getX(), event.getY());
			else if(event.getAction() == MotionEvent.ACTION_UP)
				this._touchScreenListener.onRelease(event.getX(), event.getY());
			
			try 
			{
				Thread.sleep(30);
			} 
			catch (Exception e) 
			{
			}
			return true;
		}
		return false;
	}
	//====================================
	// TODO: Music manager calls
	//====================================	
	public float musicGetMasterVolume()
	{
		return this._musicManager.masterVolume();
	}
	public void musicSetMasterVolume(float volume)
	{
		this._musicManager.masterVolume(volume);
	}
	public void musicRemove(G3DMusic music)
	{
		this._musicManager.removeMusic(music);
	}
	public void musicRemoveAll()
	{
		this._musicManager.destroy();
	}
	public G3DMusic musicCreateFromFile(File file)throws IOException
	{
		MediaPlayer mediaPlayer = new MediaPlayer();
		
		mediaPlayer.setDataSource(new FileInputStream(file).getFD());
		mediaPlayer.prepare();
		
		G3DMusic music = new G3DMusic(mediaPlayer, this._musicManager);
		this._musicManager.addMusic(music);
		return music;
	}
	public G3DMusic musicCreateFromAsset(String assetFile)throws IOException
	{
		MediaPlayer mediaPlayer = new MediaPlayer();

		AssetFileDescriptor assetFileDescritor = this.getAssets().openFd(assetMusicPath + assetFile);
		mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(), assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());
		mediaPlayer.prepare();
		
		G3DMusic music = new G3DMusic(mediaPlayer, this._musicManager);
		this._musicManager.addMusic(music);
		return music;
	}
	public G3DMusic musicCreateFromResource(int resourceId)throws IOException
	{
		final MediaPlayer mediaPlayer = MediaPlayer.create(this, resourceId);
		mediaPlayer.prepare();

		G3DMusic music = new G3DMusic(mediaPlayer, this._musicManager);
		this._musicManager.addMusic(music);
		return music;
	}
	
	//====================================
	// TODO: Sound manager calls
	//====================================	
	public float soundGetMasterVolume()
	{
		return this._soundManager.masterVolume();
	}
	public void soundSetMasterVolume(float volume)
	{
		this._soundManager.masterVolume(volume);
	}
	public void soundRemove(G3DSound sound)
	{
		this._soundManager.removeSound(sound);
	}
	public void soundRemoveAll()
	{
		this._soundManager.destroy();
	}
	public G3DSound soundCreateFromFile(String file)throws IOException
	{
		int soundId = this._soundManager.getSoundPool().load(file, 1);
		G3DSound sound = new G3DSound(soundId, this._soundManager);
		this._soundManager.addSound(sound);
		
		return sound;
	}
	public G3DSound soundCreateFromAsset(String assetFile)throws IOException
	{
		int soundId = this._soundManager.getSoundPool().load(this.getAssets().openFd(assetSoundPath + assetFile), 1);
		G3DSound sound = new G3DSound(soundId, this._soundManager);
		this._soundManager.addSound(sound);
		
		return sound;
	}
	public G3DSound soundCreateFromResource(int resourceId)throws IOException
	{
		int soundId = this._soundManager.getSoundPool().load(this, resourceId, 1);
		G3DSound sound = new G3DSound(soundId, this._soundManager);
		this._soundManager.addSound(sound);
		
		return sound;
	}
	public G3DSound soundCreateFromFileDescriptor(FileDescriptor fileDesc, long offset, long length)throws IOException
	{
		int soundId = this._soundManager.getSoundPool().load(fileDesc, offset, length, 1);
		G3DSound sound = new G3DSound(soundId, this._soundManager);
		this._soundManager.addSound(sound);
		
		return sound;
	}
	
	//===========================================
	// TODO: Listener setters
	//===========================================
	public void setToucheScreenListener(IG3DTouchScreen listener)
	{
		this._touchScreenListener = listener;
	}
	
	public void setEngineListener(IG3DEngineListener listener)
	{
		this._engineListener = listener;
	}
}